﻿using Autoupdate.Common;
using CC.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace GDF.AutoupdateConfig
{
    public partial class VersionEditForm : Form
    {
        public const string RecentFile = "RecentFile";

        private DataTable mVersionTable;
        private int mVersionIndex;
        private DataTable mFileTable;
        private Configuration mConfig;
        private string mRecentFile;
        private string mHisFile = "history.his";

        public VersionEditForm(ComboBox.ObjectCollection moduleItems, int moduleIndex, DataTable versionTable, int versionIndex)
        {
            InitializeComponent();

            mConfig = new Configuration(null);
            mRecentFile = string.Empty;

            foreach (object obj in moduleItems)
                cboModule.Items.Add(obj.ToString());
            cboModule.SelectedIndex = moduleIndex;

            mVersionTable = versionTable;
            mVersionIndex = versionIndex;

            if (mVersionIndex != -1)
            {
                txtName.Text = mVersionTable.Rows[mVersionIndex][SysUpdateVersion.Name].ToString();
                txtDescription.Text = mVersionTable.Rows[mVersionIndex][SysUpdateVersion.Description].ToString();
            }

            mFileTable = new DataTable();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            try
            {
                mConfig.Load(Path.Combine(Application.StartupPath, MainForm.ConfigFile));
                mRecentFile = mConfig.ReadString(cboModule.Text + RecentFile);

                if (mVersionIndex != -1)
                {
                    DBHelper.FillTable("SELECT * FROM " + SysUpdateFile.TableName
                        + " WHERE " + SysUpdateVersion.Id + "='" + mVersionTable.Rows[mVersionIndex][SysUpdateVersion.Id].ToString() + "'",
                        mFileTable);
                    mFileTable.Columns.Add(SysUpdateFile.Status);
                    UpdateFileView();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + ex.StackTrace,
                    "错误",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
            if (File.Exists(mHisFile))
            {
                MyConfiguration cfg = new MyConfiguration(mHisFile, false);
                
                if (cfg.ContainsKey(cboModule.Text + ".SrcPath"))
                {
                    txtPath.Text = cfg.ReadString(cboModule.Text + ".SrcPath");
                }
            }
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);
            try
            {
                mConfig.Save(Path.Combine(Application.StartupPath, MainForm.ConfigFile));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + ex.StackTrace,
                    "错误",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        private void btnReadFiles_Click(object sender, EventArgs e)
        {
            if (cboModule.SelectedIndex <= 0) return;
            string moduleName = cboModule.Text;
            try
            {
                string srcPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                if (File.Exists(mHisFile))
                {
                    MyConfiguration cfg = new MyConfiguration(mHisFile, false);
                    if (cfg.ContainsKey("SrcPath"))
                    {
                        srcPath = cfg.ReadString("SrcPath");
                    }
                    if (cfg.ContainsKey(cboModule.Text+".SrcPath"))
                    {
                        srcPath = cfg.ReadString(cboModule.Text + ".SrcPath");
                    }
                }
               
                FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
                folderBrowserDialog.SelectedPath = srcPath;
                if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
                {
                    MyConfiguration cfg = new MyConfiguration(false);
                    if (File.Exists(mHisFile)) cfg.Load(mHisFile);
                    cfg.WriteString(cboModule.Text + ".SrcPath", folderBrowserDialog.SelectedPath);
                    cfg.Save(mHisFile);

                    this.Cursor = Cursors.WaitCursor;

                    mRecentFile = folderBrowserDialog.SelectedPath;
                    mConfig.WriteString(cboModule.Text + RecentFile, mRecentFile, true);
                    txtPath.Text = folderBrowserDialog.SelectedPath;
                    mFileTable.Rows.Clear();

                    var localFiles = Directory.GetFiles(folderBrowserDialog.SelectedPath);

                    if (mFileTable.Columns.Count == 0)
                    {
                        DBHelper.FillTable("SELECT * FROM " + SysUpdateFile.TableName + " WHERE 1=2", mFileTable);
                        mFileTable.Columns.Add(SysUpdateFile.Status);
                    }
                    if (string.IsNullOrEmpty(cboModule.Text))
                    {
                        foreach (string file in localFiles)
                        {
                            DataRow newRow = mFileTable.NewRow();
                            newRow[SysUpdateFile.Name] = Path.GetFileName(file);
                            newRow[SysUpdateFile.Path] = Util.GetRelativePath(folderBrowserDialog.SelectedPath, file);
                            newRow[SysUpdateFile.MD5] = Util.GetFileMD5(file);
                            newRow[SysUpdateFile.Data] = Util.StreamToBytes(Util.FileToStream(file));
                            newRow[SysUpdateFile.Status] = "新增";
                            mFileTable.Rows.Add(newRow);
                        }
                    }
                    else
                    {
                        using (DataTable serverFileTable = new DataTable())
                        {
                            string cmd = "EXEC Sys_Update_GetFiles " + cboModule.Text + ", 1";
                            if (mVersionIndex != -1)
                                cmd += ", 1";
                            DBHelper.FillTable(cmd, serverFileTable);
                            if (serverFileTable.Rows.Count > 0)
                            {
                                List<int> serverExtraFiles = new List<int>();
                                List<int> localExtraFiles = new List<int>();
                                List<int> localUpdateFiles = new List<int>();
                                Autoupdate.Common.Common.CompareFiles(folderBrowserDialog.SelectedPath, serverFileTable, localFiles.ToList(), serverExtraFiles, null, localExtraFiles, localUpdateFiles);
                                foreach (int i in serverExtraFiles)
                                {
                                    DataRow newRow = mFileTable.NewRow();
                                    newRow[SysUpdateVersion.Id] = serverFileTable.Rows[i][SysUpdateVersion.Id].ToString();
                                    newRow[SysUpdateFile.Name] = serverFileTable.Rows[i][SysUpdateFile.Name].ToString();
                                    newRow[SysUpdateFile.Path] = serverFileTable.Rows[i][SysUpdateFile.Path].ToString();
                                    newRow[SysUpdateFile.MD5] = serverFileTable.Rows[i][SysUpdateFile.MD5].ToString();
                                    newRow[SysUpdateFile.Data] = DBNull.Value; // 表示更新时要删除
                                    newRow[SysUpdateFile.Status] = "删除";
                                    mFileTable.Rows.Add(newRow);
                                }
                                foreach (int i in localUpdateFiles)
                                {
                                    DataRow newRow = mFileTable.NewRow();
                                    newRow[SysUpdateFile.Name] = Path.GetFileName(localFiles[i]);
                                    newRow[SysUpdateFile.Path] = Util.GetRelativePath(folderBrowserDialog.SelectedPath, localFiles[i]);
                                    newRow[SysUpdateFile.MD5] = Util.GetFileMD5(localFiles[i]);
                                    newRow[SysUpdateFile.Data] = Util.StreamToBytes(Util.FileToStream(localFiles[i]));
                                    newRow[SysUpdateFile.Status] = "覆盖";
                                    mFileTable.Rows.Add(newRow);
                                }
                                foreach (int i in localExtraFiles)
                                {
                                    DataRow newRow = mFileTable.NewRow();
                                    newRow[SysUpdateFile.Name] = Path.GetFileName(localFiles[i]);
                                    newRow[SysUpdateFile.Path] = Util.GetRelativePath(folderBrowserDialog.SelectedPath, localFiles[i]);
                                    newRow[SysUpdateFile.MD5] = Util.GetFileMD5(localFiles[i]);
                                    newRow[SysUpdateFile.Data] = Util.StreamToBytes(Util.FileToStream(localFiles[i]));
                                    newRow[SysUpdateFile.Status] = "新增";
                                    mFileTable.Rows.Add(newRow);
                                }

                                // 设置当前文件列表中与历史版本中忽略文件同路径的文件为忽略文件
                                // 设置当前文件列表中与历史版本中启动文件同路径的文件为启动文件
                                foreach (DataRow dr in mFileTable.Rows)
                                {
                                    foreach (DataRow row in serverFileTable.Rows)
                                    {
                                        if (row[SysUpdateFile.Path].ToString() == dr[SysUpdateFile.Path].ToString()
                                            && (row[SysUpdateFile.Usage].ToString() == FileUsage.Ignore
                                            || row[SysUpdateFile.Usage].ToString() == FileUsage.Run
                                            || row[SysUpdateFile.Usage].ToString() == FileUsage.Icon))
                                        {
                                            dr[SysUpdateFile.Usage] = row[SysUpdateFile.Usage].ToString();
                                            break;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                foreach (string file in localFiles)
                                {
                                    DataRow newRow = mFileTable.NewRow();
                                    newRow[SysUpdateFile.Name] = Path.GetFileName(file);
                                    newRow[SysUpdateFile.Path] = Util.GetRelativePath(folderBrowserDialog.SelectedPath, file);
                                    newRow[SysUpdateFile.MD5] = Util.GetFileMD5(file);
                                    newRow[SysUpdateFile.Data] = Util.StreamToBytes(Util.FileToStream(file));
                                    newRow[SysUpdateFile.Status] = "新增";
                                    mFileTable.Rows.Add(newRow);
                                }
                            }
                        }
                    }

                    UpdateFileView();

                    this.Cursor = Cursors.Default;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + ex.StackTrace,
                    "错误",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        private void btnAddIgnoreFiles_Click(object sender, EventArgs e)
        {
            try
            {
                if (string.IsNullOrEmpty(txtPath.Text))
                {
                    MessageBox.Show("请先选择文件目录！",
                        "错误",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
                    return;
                }
                OpenFileDialog fileDialog = new OpenFileDialog();
                fileDialog.InitialDirectory = txtPath.Text;
                fileDialog.Multiselect = true;
                if (fileDialog.ShowDialog() == DialogResult.OK)
                {
                    this.Cursor = Cursors.WaitCursor;

                    string[] selectedFiles = fileDialog.FileNames;
                    bool find = false;
                    foreach (string file in selectedFiles)
                    {
                        find = false;
                        string path = Util.GetRelativePath(txtPath.Text, file);
                        foreach (DataRow dr in mFileTable.Rows)
                        {
                            if (dr[SysUpdateFile.Path].ToString() == path)
                            {
                                find = true;
                                break;
                            }
                        }
                        if (find)
                            continue;
                        DataRow newRow = mFileTable.NewRow();
                        newRow[SysUpdateFile.Name] = Path.GetFileName(file);
                        newRow[SysUpdateFile.Path] = path;
                        newRow[SysUpdateFile.MD5] = Util.GetFileMD5(file);
                        newRow[SysUpdateFile.Data] = Util.StreamToBytes(Util.FileToStream(file));
                        newRow[SysUpdateFile.Usage] = FileUsage.Ignore;
                        mFileTable.Rows.Add(newRow);
                    }

                    UpdateFileView();

                    this.Cursor = Cursors.Default;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + ex.StackTrace,
                    "错误",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            try
            {
                this.Cursor = Cursors.WaitCursor;
                if (string.IsNullOrEmpty(cboModule.Text))
                {
                    MessageBox.Show("模块名称不能为空!",
                        "错误",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
                    this.Cursor = Cursors.Default;
                    return;
                }
                if (string.IsNullOrEmpty(txtName.Text))
                {
                    MessageBox.Show("版本号不能为空!",
                        "错误",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
                    this.Cursor = Cursors.Default;
                    return;
                }
                for (int i = 0; i < mVersionTable.Rows.Count; ++i)
                {
                    if (i == mVersionIndex)
                        continue;
                    if (mVersionTable.Rows[i][SysUpdateVersion.Name].ToString() == txtName.Text)
                    {
                        MessageBox.Show("版本号'" + txtName.Text + "'已经存在，不能重复添加!",
                            "错误",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Error);
                        this.Cursor = Cursors.Default;
                        return;
                    }
                }
                if (mFileTable == null || mFileTable.Columns.Count == 0 || mFileTable.Rows.Count == 0)
                {
                    MessageBox.Show("没有可更新的文件！",
                        "提示",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information);
                    this.Cursor = Cursors.Default;
                    return;
                }

                List<string> runFiles = new List<string>();
                // 先看本地要上传的文件中有没有启动文件
                foreach (DataRow dr in mFileTable.Rows)
                {
                    // 文件索引不为空，说明不是本地文件
                    if (!string.IsNullOrEmpty(dr[SysUpdateVersion.Id].ToString()))
                        continue;                   
                    if (dr[SysUpdateFile.Path].ToString().ToUpper().EndsWith(".EXE") 
                        && dr[SysUpdateFile.Usage].ToString() == FileUsage.Run)
                    {
                        if (!runFiles.Contains(dr[SysUpdateFile.Path].ToString()))
                            runFiles.Add(dr[SysUpdateFile.Path].ToString());
                    }
                }
                if (runFiles.Count > 1)
                {
                    StringBuilder builder = new StringBuilder();
                    builder.Append("不能指定多个启动文件:\n");
                    foreach (string file in runFiles)
                        builder.Append(file + "\n");
                    MessageBox.Show(builder.ToString(),
                        "错误",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
                    this.Cursor = Cursors.Default;
                    return;
                }
                if (runFiles.Count == 0)
                {
                    using (DataTable serverFileTable = new DataTable())
                    {
                        string strCmd = "EXEC Sys_Update_GetFiles " + cboModule.Text + ", 1";
                        if (mVersionIndex != -1)
                            strCmd += ", 1";
                        DBHelper.FillTable(strCmd, serverFileTable);
                        if (serverFileTable.Rows.Count > 0)
                        {
                            foreach (DataRow dr in serverFileTable.Rows)
                            {
                                foreach (DataRow row in mFileTable.Rows)
                                {
                                    if (row[SysUpdateFile.Path].ToString() == dr[SysUpdateFile.Path].ToString())
                                    {
                                        dr[SysUpdateFile.Usage] = row[SysUpdateFile.Usage];
                                        break;
                                    }
                                }
                                if (dr[SysUpdateFile.Path].ToString().ToUpper().EndsWith(".EXE") && dr[SysUpdateFile.Usage].ToString() == FileUsage.Run)
                                {
                                    if (!runFiles.Contains(dr[SysUpdateFile.Path].ToString()))
                                        runFiles.Add(dr[SysUpdateFile.Path].ToString());
                                }
                            }
                        }
                    }
                    if (runFiles.Count == 0)
                    {
                        MessageBox.Show("请先指定启动文件！",
                            "错误",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Error);
                        this.Cursor = Cursors.Default;
                        return;
                    }
                }

                SqlConnection conn = new SqlConnection(DBHelper.ConnectionString);
                SqlCommand cmd = new SqlCommand();
                cmd.Connection = conn;
                SqlTransaction trans = null;
                try
                {
                    conn.Open();
                    trans = conn.BeginTransaction();//开启事务  
                    cmd.Transaction = trans;

                    if (mVersionIndex == -1)
                    {
                        cmd.CommandText = "INSERT INTO " + SysUpdateVersion.TableName
                            + "(" + SysUpdateVersion.Module + "," + SysUpdateVersion.Name + "," + SysUpdateVersion.Description + "," + SysUpdateVersion.Time + "," + SysUpdateVersion.Locked + ")"
                            + " VALUES('" + cboModule.Text + "','" + txtName.Text + "','" + txtDescription.Text + "', GETDATE(), 1)";
                        cmd.ExecuteNonQuery();
                    }
                    else
                    {
                        cmd.CommandText = "UPDATE " + SysUpdateVersion.TableName
                            + " SET " + SysUpdateVersion.Module + "='" + cboModule.Text + "',"
                            + SysUpdateVersion.Name + "='" + txtName.Text + "',"
                            + SysUpdateVersion.Description + "='" + txtDescription.Text + "',"
                            + SysUpdateVersion.Time + "=GETDATE(),"
                            + SysUpdateVersion.Locked + "=1"
                            + " WHERE " + SysUpdateVersion.Id + "=" + mVersionTable.Rows[mVersionIndex][SysUpdateVersion.Id].ToString();
                        cmd.ExecuteNonQuery();

                        cmd.CommandText = "DELETE FROM " + SysUpdateFile.TableName
                            + " WHERE " + SysUpdateVersion.Id + "=" + mVersionTable.Rows[mVersionIndex][SysUpdateVersion.Id].ToString();
                        cmd.ExecuteNonQuery();
                    }

                    string id = "(SELECT " + SysUpdateVersion.Id + " FROM " + SysUpdateVersion.TableName
                        + " WHERE " + SysUpdateVersion.Module + "='" + cboModule.Text + "'"
                        + " AND " + SysUpdateVersion.Name + "='" + txtName.Text + "')";
                    foreach (DataRow dr in mFileTable.Rows)
                    {
                        cmd.CommandText = "INSERT INTO " + SysUpdateFile.TableName
                            + "(" + SysUpdateVersion.Id + "," + SysUpdateFile.Name + "," + SysUpdateFile.Path + ","
                            + SysUpdateFile.MD5 + "," + SysUpdateFile.Data + "," + SysUpdateFile.Usage + ")"
                            + " VALUES(" + id + ", '" + dr[SysUpdateFile.Name].ToString() + "', '" + dr[SysUpdateFile.Path].ToString() + "',"
                            + " '" + dr[SysUpdateFile.MD5].ToString() + "', @data, '" + dr[SysUpdateFile.Usage].ToString() + "')";
                        cmd.Parameters.Clear();
                        cmd.Parameters.Add(new SqlParameter("@data", SqlDbType.VarBinary)).Value = dr[SysUpdateFile.Data];
                        cmd.ExecuteNonQuery();
                    }
                    trans.Commit();//提交事务  
                    this.Cursor = Cursors.Default;
                    this.DialogResult = DialogResult.OK;
                }
                catch (Exception ex)
                {
                    if (trans != null)
                        trans.Rollback();
                    //throw ex;
                    MessageBox.Show(ex.Message + ex.StackTrace,
                        "错误",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
                    this.Cursor = Cursors.Default;
                }
                finally
                {
                    if (trans != null)
                        trans.Dispose();
                    conn.Close();
                    conn.Dispose();
                    this.Cursor = Cursors.Default;
                }
                if (mVersionIndex == -1)
                    MessageBox.Show("版本'" + txtName.Text + "'新增成功！",
                        "提示",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information);
                else
                    MessageBox.Show("版本'" + txtName.Text + "'编辑成功！",
                        "提示",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information);
                this.Cursor = Cursors.Default;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + ex.StackTrace,
                    "错误",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        private void dgvFileList_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
        {
            DataGridView dgv = sender as DataGridView;
            e.Graphics.DrawString((e.RowIndex + 1).ToString(),
                this.Font,
                SystemBrushes.ControlText,
                new Rectangle(e.RowBounds.Left, e.RowBounds.Top, dgv.RowHeadersWidth, e.RowBounds.Height),
                new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
        }

        private void UpdateFileView()
        {
            MainForm.UpdateFileView(dgvFileList, mFileTable, true, true);
            if (mFileTable == null || mFileTable.Columns.Count == 0 || mFileTable.Rows.Count == 0)
                lblFileCount.Text = "文件总数:(0)";
            else
                lblFileCount.Text = "文件总数:(" + mFileTable.Rows.Count + ")";
        }

        private void VersionEditForm_Load(object sender, EventArgs e)
        {

        }

        private void cboModule_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void txtName_Validated(object sender, EventArgs e)
        {
            if(string.IsNullOrEmpty(txtPath.Text))
            {
                btnReadFiles_Click(sender, e);
            }
        }
    }
}
